#@author Devdoer<devdoer@gmail.com>
#
from anole import AnoleLog,AnoleError


'''
Each content type has some processors.
Each processor processes several content types.
See below charts:
	content-type1:processor1->processor2->processor3
	content-type2:processor2->processor4->....->processorN
	content-type3:processor4->processor1->processor2
The above discription applies to the head-type as well.
'''

        

class CrawlApp:
    #shared object	
    def __init__(self):
        self._conPMap={}
        self._headPMap={}
	self._errPs=set()
	self._cmdPs=set()
        self._log=AnoleLog().log
    def reg_error_p(self,p):
	self._errPs.add(p)
    def reg_error_ps(self,ps):
    	for p in ps:
		self.reg_error_p(p)
    def reg_cmd_p(self,p):
	self._cmdPs.add(p)
    def reg_cmd_ps(self,ps):
    	for p in ps:
		self.reg_cmd_p(p)
    def reg_content_p(self,p,contentTypes=None):
	if not contentTypes:
		contentTypes=p.content_types()
        #print contentTypes
        for cT in contentTypes:
	    print cT
            try:
                self._conPMap[cT]
            except KeyError:
                self._conPMap[cT]=set()

            self._conPMap[cT].add(p)
    def reg_content_ps(self,ps):
    	for p in ps:
		self.reg_content_p(p)
    def reg_head_p(self,p,codes=None):
	if not codes:
		codes=p.codes()
     
        for c in codes:
            try:
                self._headPMap[c]
            except KeyError:
                self._headPMap[c]=set()

            self._headPMap[c].add(p)
    def reg_head_ps(self,ps):
    	for p in ps:
		self.reg_head_p(p)
    def on_anole_error(self,err,req):
        self._log('CrawlApplication::on_anole_error()',AnoleLog.LEVEL_DEBUG)
	for p in self._errPs:
		p.process_anole_error(err,req)
    def on_anole_cmd(self,cmd):
        self._log('CrawlApplication::on_anole_cmd()',AnoleLog.LEVEL_DEBUG)
	ps=self._cmdPs
	for p in ps:
		p.process_anole_cmd(cmd)
    def on_http_head_ok(self,head,request):
        #return :False ,not process reply file any more
        #print head
        self._log('CrawlApplication::head_ok()',AnoleLog.LEVEL_DEBUG)
        replyCode=head['code']
        self._log('reply code is %d'%replyCode,AnoleLog.LEVEL_DEBUG)
        
        methodName='process_'+`replyCode`
        try:
            ps= self._headPMap[replyCode]
            
        except KeyError:
            pass
        else:
		for p in ps:
		    try:
			method=getattr(p,methodName)
		    except AttributeError:
			method=getattr(p,'process_head')
		    method(head,request)    
        
        #indicate whether we should process this request any longer
        #true means 'yes',flase menas 'no'    
        if replyCode==200:
            return True
        else:
            #-1,10X,30X,40X,50X
            return False
            
       
            
    def on_http_reply_ok(self,reply,request):
        self._log('CrawlApplication::reply_ok()',AnoleLog.LEVEL_DEBUG)
        #print '\n\n------------------------------------------------------'
        replyHead=reply.get_head()
        contentFile=reply.get_file()
        #print contentFile.read()
        
        try:
            contentType=replyHead['content-type']
            
        except KeyError:
            self._log('process %s,no content-type defined,reply-head is %s' \
                      %(request.strUrl,str(replyHead)),AnoleLog.LEVEL_WARNING)
            
            return
            
        else:
            contentType=contentType.lower()
            idx=contentType.find(';')
            if idx!=-1:
                contentType=contentType[:idx]
        self._log('content-type is %s'%contentType,AnoleLog.LEVEL_DEBUG)    
        name=contentType.replace('/','_')
        methodName='process_'+name.replace('-','_')
        self._log('processor method  is: %s'%methodName,AnoleLog.LEVEL_DEBUG)
        try:
            ps= self._conPMap[contentType]
        except KeyError:
            pass
        else:
 		 for p in ps:
            
            		try:
               			method=getattr(p,methodName)
            		except AttributeError:
                		method=getattr(p,'process_content')
                	contentFile.reset()
            		method(replyHead,contentFile,request)        		
           
            
      
